# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="jonathan"
__date__ ="$24-May-2010 20:38:45$"

from math import atan2, cos, sin, radians, degrees, sqrt
import pygame


def view_boundary(view, screen_rect, offset=0):
    """Map the screen_rect onto the view and then return a rectangle that
    contains the resulting rhombus so that fast collidepoint and colliderect
    functions can be use to determine if a GameObject is on screen.
    """
    X, Y, W, H = screen_rect
    A, B, C, D = view.from_view(
        ((X - offset[0], Y - offset[1], 0),
         (X + W + offset[0], Y - offset[1], 0),
         (X + W + offset[0], Y + H + offset[1], 0),
         (X - 2 * offset[0], Y + H + 2 * offset[1], 0)))

    min_x = min(A[0], B[0], C[0], D[0])
    max_x = max(A[0], B[0], C[0], D[0])
    min_y = min(A[1], B[1], C[1], D[1])
    max_y = max(A[1], B[1], C[1], D[1])

    return pygame.Rect(min_x, min_y, max_x - min_x, max_y - min_y)


def collide_rhombus(lines, centre, point):
    """detects if a point is inside a rhombus by dividing the rhombus into
    4 triangles and tests if the point is inside each triangle.
    """
    for line in lines:
        triangle = line + (centre,)
        if collide_triangle(triangle, point):
            return True
    return False


def collide_triangle(triangle, p):
    """detect if a point is inside a triangle.

    see reference: http://www.blackpawn.com/texts/pointinpoly/default.html
    """
    a,b,c = triangle
    if same_side(p,a,b,c) and same_side(p,b,a,c) and same_side(p,c,a,b):
        return True
    else:
        return False


def same_side(p1,p2,a,b):
    cp1 = cross_product((b[0]-a[0],b[1]-a[1]), (p1[0]-a[0],p1[1]-a[1]))
    cp2 = cross_product((b[0]-a[0],b[1]-a[1]), (p2[0]-a[0],p2[1]-a[1]))
    if cmp(cp1,0) == cmp(cp2,0):
        return True
    else:
        return False


def cross_product(a,b):
    a1,a2 = a
    b1,b2 = b
    return a1*b2 - a2*b1


def calc_angle(p1, p2, to_screen=True):
    """calculate the angle between points p1 and p2"""
    x1,y1 = p1[:2]
    x2,y2 = p2[:2]
    # translate p1 to origin 0,0; translate p2 towards origin by same amount
    x1,y1 = p1[:2]
    x2,y2 = p2[:2]
    t1 = 0,0
    t2 = x2-x1,y2-y1
    # put the new values back for code readability
    x1,y1 = t1
    x2,y2 = t2
    # base image always "points" in this direction
    if to_screen:
        y1 = -y1
        y2 = -y2
    deg = degrees(atan2(y1,x1) - atan2(y2,x2))
    # correct out of bounds
    deg %= 360
    return deg


def calc_circumference_point(radius, origin, degrees_, to_screen=True):
    """calculate a point on the circumference of a circle defined by an
    origin, radius, and angle"""
    x1,y1 = 0,0
    if to_screen:
        degrees_ -= 90
    radians_ = radians(degrees_)
    x = x1 + radius * cos(radians_)
    y = y1 + radius * sin(radians_)
    # translate coordinates to game space
    x += origin[0]
    y += origin[1]
    return x,y


def distance(a, b):
    """Calculate the distance between points a and b.

    Returns distance as a float.
    a and b should be float. a is point x1,y1, b is point x2,y2.
    """
    diffx = a[0] - b[0]
    diffy = a[1] - b[1]
    return sqrt(pow(diffx,2) + pow(diffy,2))
